
package com.smallrig.extension.ext;

import com.smallrig.extension.ExtensionSpi;
import com.smallrig.extension.dto.BizSceneWrapper;
import com.smallrig.extension.ExtensionException;
import com.smallrig.extension.dto.BizScene;
import com.smallrig.extension.dto.BizScenes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

public class ExtensionExecutor extends AbstractComponentExecutor {

    private static final String EXTENSION_NOT_FOUND = "extension_not_found";

    private Logger logger = LoggerFactory.getLogger(ExtensionExecutor.class);

    private static final Comparator<Object> COMPARATOR = new AnnotationAwareOrderComparator();

    @Resource
    private ExtensionRepository extensionRepository;

    @Override
    protected <C> C locateComponent(Class<C> targetClz, BizScene bizScene) {
        List<C> components = locateComponent(targetClz, BizScenes.valueOf(bizScene));
        return components.get(0);
    }

    @Override
    protected <C> List<C> locateComponent(Class<C> targetClz, BizScenes bizScenes) {
        List<C> extensions = locateExtension(targetClz, bizScenes);
        for (C extension : extensions) {
            logger.debug("[Located Extension]: " + extension.getClass().getSimpleName());
        }
        return extensions;
    }

    protected <Ext> List<Ext> locateExtension(Class<Ext> targetClz, BizScenes bizScenes) {
        for (BizScene bizScene : bizScenes.getBizSceneList()) {
            logger.debug("BizScenario in locateExtension is : " + bizScene.getUniqueIdentity());
        }
        Map<BizSceneWrapper, ExtensionSpi> spiMap = extensionRepository.get(targetClz.getName());

        List<Ext> exts = new ArrayList<>();
        for (Map.Entry<BizSceneWrapper, ExtensionSpi> spiEntry : spiMap.entrySet()) {
            if(bizScenes.contains(spiEntry.getKey().getUniqueIdentity())){
                exts.add((Ext) spiEntry.getValue());
            }
        }

        if(!CollectionUtils.isEmpty(exts)){
            Collections.sort(exts, COMPARATOR);
            return exts;
        }

        String errMessage = "Can not find extension with ExtensionPoint: " + targetClz;
        throw new ExtensionException(EXTENSION_NOT_FOUND, errMessage);
    }


    private void checkNull(BizScene bizScenario) {
        if (bizScenario == null) {
            throw new IllegalArgumentException("BizScenario can not be null for extension");
        }
    }

}
